<!DOCTYPE html>
<html lang="zh">
	<head>
		<meta charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<title>canvas粒子连线效果</title>
		<style>
			* {
				margin: 0;
				padding: 0;
			}
			body {
				overflow: hidden;
			}
		</style>
	</head>
	<body>
		<canvas style="background-color: #000"></canvas>
		<script>
			// 获取元素
			const can = document.querySelector("canvas");
			// 获取屏幕宽高
			const w = window.innerWidth;
			const h = window.innerHeight;

			// 设置画布宽高
			can.width = w;
			can.height = h;

			// 获取画笔
			const ctx = can.getContext("2d");

			// 定义球类
			class Circle {
				// 传入球的坐标
				constructor(x, y) {
					this.x = x;
					this.y = y;
					this.r = Math.random() * 10 + 5; //随机大小
					this.color = "rgba(0,255,0,0.3)"; //球和线的颜色
					this.px = Math.random(); //偏移位置
					this.py = Math.random();
				}

				// 绘制球的方法
				render(ctx) {
					ctx.beginPath();
					ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2, true);
					ctx.fillStyle = this.color;
					ctx.closePath();
					ctx.fill();
				}

				// 球之间的连线方法
				line(ctx, circle) {
					const lx = this.x - circle.x;
					const ly = this.y - circle.y;
					// 算出2个球心的距离
					const lr = Math.sqrt(lx * lx + ly * ly);
					// 判断球心之间的距离小于100就连线
					if (lr < 100) {
						ctx.beginPath();
						ctx.moveTo(this.x, this.y);
						ctx.lineTo(circle.x, circle.y);
						ctx.strokeStyle = this.color;
						ctx.closePath();
						ctx.stroke();
					}
				}

				// 移动方法,传入屏幕的宽高不让球出去
				move(w, h) {
					this.px = this.x < w && this.x > 0 ? this.px : -this.px;
					this.py = this.y < h && this.y > 0 ? this.py : -this.py;
					this.x += this.px;
					this.y += this.py;
				}
			}

			//    放球的数组
			const circleArr = [];

			// 创建球
			for (let i = 0; i < 150; i++) {
				// 存到数组中
				circleArr.push(new Circle(Math.random() * w, Math.random() * h));
			}

			// 创建一个鼠标控制的球
			const base = new Circle(Math.random() * w, Math.random() * h);
			// 加到数组中
			circleArr.push(base);

			// 监听鼠标移动
			document.onmousemove = (e) => {
				// 改变鼠标控制的球的位置
				base.x = e.clientX;
				base.y = e.clientY;
			};

			// 定时器刷新界面
			// setInterval(() => {
			// 	// 先清掉上一次的画面
			// 	ctx.clearRect(0, 0, w, h);

			// 	circleArr.forEach((item) => {
			// 		// 让球移动
			// 		item.move(w, h);
			// 		item.render(ctx);
			// 		// 判断球之间是否能连线
			// 		circleArr.forEach((item1) => {
			// 			if (item === item1) return;
			// 			item.line(ctx, item1);
			// 		});
			// 	});
			// },30);

			const draw = () => {
				// 先清掉上一次的画面
				ctx.clearRect(0, 0, w, h);

				circleArr.forEach((item) => {
					// 让球移动
					item.move(w, h);
					item.render(ctx);
					// 判断球之间是否能连线
					circleArr.forEach((item1) => {
						if (item === item1) return;
						item.line(ctx, item1);
					});
				});
                requestAnimationFrame(draw)
			};

			requestAnimationFrame(draw);
		</script>
	</body>
</html>